﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.Collections;
using System.Xml;
using HAP = HtmlAgilityPack;
using System.Windows.Forms;
using TaobaoPick.util;

namespace TaobaoPick.storage
{
   public class CategoryExploreContext
    {

       Queue<Hashtable> toProcess = new Queue<Hashtable>();
       public String getDesc()
       {
           String r="To Process:"+toProcess.Count+"\r\n";

           foreach (Hashtable ht in toProcess)
           {
               r+=ht["name"]+"\r\n";
           }
           return r; 
       }
       public CategoryExploreContext()
       {
       }

        public String process(String url,String content)
       {
           processCat(url, content);
           if(toProcess.Count>0)
           {
               Hashtable ht=toProcess.Dequeue();
               String r=(String)ht["url"];
               return r;
           }else
               return null;
       }

       protected void putToQueue(String name,String url)
       {
           if (String.IsNullOrWhiteSpace(name))
               return;
           Hashtable ht = new Hashtable();
           ht["name"] = name;
           ht["url"] = url;
           toProcess.Enqueue(ht);
       }

       protected void updateCategory(String name, String code,bool isLeaf)
       {
           MyTaobao1DataContext context=LinqAgent.getTaobaoContext();
           if (String.IsNullOrWhiteSpace(code))
               return;
           TaobaoPick.Category ct = (from cat in context.Categories where cat.categoryName.Equals(name) select cat).FirstOrDefault();
           if (ct == null)
           {
               ct = new Category();
               ct.categoryName = name;
               ct.categoryCode = code;
               ct.categoryId = NewGUID.create("cate");
               ct.categoryLevel = 5;
               ct.isLeaf=isLeaf;
               ct.seq = name.Length;
               context.Categories.InsertOnSubmit(ct);
               context.SubmitChanges();
           }
           else
           {
               if(String.IsNullOrWhiteSpace(code)==false)
                   if (code.Equals(ct.categoryCode) == false)
               {
                   ct.categoryCode = code;
               }
               if (ct.isLeaf != isLeaf)
               {
                   ct.isLeaf = isLeaf;
               }
               context.SubmitChanges();
           }
           

       }
       protected void updateCategoryAndParent(String name, String code,String parentCode)
       {
           MyTaobao1DataContext context = LinqAgent.getTaobaoContext();
           TaobaoPick.Category parent = null;
           if(String.IsNullOrWhiteSpace(parentCode)==false)
               parent=(from cat in context.Categories where cat.categoryCode.Equals(parentCode) select cat).FirstOrDefault();
           TaobaoPick.Category ct = (from cat in context.Categories where cat.categoryName.Equals(name) select cat).FirstOrDefault();

           if (ct == null)
           {
               ct = new Category();
               ct.categoryName = name;
               ct.categoryCode = code;
               ct.categoryId = NewGUID.create("cate");
               ct.categoryLevel = 5;
               if (parent != null)
                   ct.parentCategory = parent.categoryId;
               ct.seq = name.Length;
               context.Categories.InsertOnSubmit(ct);
               context.SubmitChanges();
           }
           else
           {
               if(String.IsNullOrWhiteSpace(code)==false)
               if (code.Equals(ct.categoryCode) == false)
               {
                   ct.categoryCode = code;
               }
               if (parent != null)
               {
                   if(parent.categoryId.Equals(ct.parentCategory)==false)
                   ct.parentCategory = parent.categoryId;
               }
               context.SubmitChanges();
           }
       }

       protected void process2Queue(List<Hashtable> cats, String urlprefix,String parentCat)
       {

           foreach (Hashtable htt in cats)
           {
               String s1 = (String)htt["text"];
               String s2 = (String)htt["cat"];
               String h = (String)htt["href"];
               if (h.StartsWith("/") == false)
               {
                   putToQueue(s1,h);
               }
               else
               {
                   putToQueue(s1,urlprefix + h);
               }
               updateCategoryAndParent(s1, s2, parentCat);
               htt.Clear();
           }
           cats.Clear();
       }
       //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       protected void processCat(String url, String content)
       {
           int lpos = url.LastIndexOf("/");
           String urlprefix = url.Substring(0, lpos);

           //1.url
           //雖然有些限制,但是如果限制在url上有cat的裁處理 是比較安全的做法
           Hashtable ht = HTMLHelpers.parseParameter(url);
           String catValue = (String)ht["cat"];

           //處理 crumbs
           HAP.HtmlDocument doc = new HAP.HtmlDocument();
           doc.LoadHtml(content);
           List<Hashtable> crumbs = processCrumb(doc);


           String[] cates={"//div[@class='cate-panel recommend-cate ']","//div[@class='cate-panel all-cate ']","//div[@class='cate-panel all-cate _NO_CLS_']","//div[@class='cate-panel all-cate  whole-line']","cate-panel hierarchy-cate"};


           //update middle crumb
           int sz = crumbs.Count;
           for (int i = 1; i < sz - 1; i++)
           {
               Hashtable htt = crumbs[i];
               String name=(String)htt["text"];
               String cat = (String)htt["cat"];
               updateCategory(name, cat, false);
           }

           List<Hashtable> allcats = new List<Hashtable>();
           foreach (String s in cates)
           {
               HAP.HtmlNode n = doc.DocumentNode.SelectSingleNode(s);
               List<Hashtable> cats1 = process_dldd(n);
               System.Diagnostics.Trace.WriteLine("total:" + cats1.Count + "\t" + s);
               allcats.AddRange(cats1);
           }


               //process Self
               if (crumbs.Count == 1)
               {
               }
               else
               {
                   bool isLeaf = true;
                   if (allcats .Count> 0)
                   {
                       isLeaf = false;
                   }
                   Hashtable lastcrumb = crumbs.Last<Hashtable>();
                   if (String.IsNullOrWhiteSpace(catValue) == false)
                   {
                       updateCategory((String)lastcrumb["text"], catValue, isLeaf);
                   }
                   //透過crumbs更新parent.
                   if (crumbs.Count > 2)
                   {
                       Hashtable htt = crumbs[crumbs.Count - 2]; 
                       String parentCat = (String)htt["cat"];
                       updateCategoryAndParent((String)lastcrumb["text"], catValue, parentCat);
                   }

               }
               process2Queue(allcats, urlprefix, catValue);
               


           
       } 

       List<Hashtable> process_dldd(HAP.HtmlNode parent)
       {
           List<Hashtable> result = new List<System.Collections.Hashtable>();
           if (parent == null)
               return result;
           HAP.HtmlNodeCollection nodes = parent.SelectNodes(parent.XPath + "/dl/dd/a");
           foreach (HAP.HtmlNode node in nodes)
           {
               String href = node.GetAttributeValue("href", "");
               if (String.IsNullOrWhiteSpace(href))
                   continue;
               href = href.Replace("&amp;", "&");
               String title = node.GetAttributeValue("title", "");
               Hashtable ht = HTMLHelpers.parseParameter(href);
               ht.Add("text", title);
               ht.Add("href", href);
               result.Add(ht);
           };
           return result;
       }

       List<Hashtable> processCrumb(HAP.HtmlDocument doc)
       {
           List<Hashtable> result = new List<System.Collections.Hashtable>();
           HAP.HtmlNode crumbs = doc.DocumentNode.SelectSingleNode("//ul[@class='crumbs']");
           if (crumbs == null)
           {
           
               return result;
           }

           HAP.HtmlNodeCollection crumblist = crumbs.SelectNodes(crumbs.XPath + "/li[@class='list-item']");
           foreach (HAP.HtmlNode node in crumblist)
           {
               Hashtable ht = new System.Collections.Hashtable();
               result.Add(ht);
               HAP.HtmlNode a = node.SelectSingleNode(node.XPath + "/a");
               if (a != null)
               {
                   String href = a.GetAttributeValue("href", "");
                   if (String.IsNullOrWhiteSpace(href) == false)
                   {
                       ht["href"] = href;
                       //href
                       //cat
                       Hashtable htt = HTMLHelpers.parseParameter(href);
                       String cat = (String)htt["cat"];
                       if (String.IsNullOrWhiteSpace(cat) == false)
                       {
                           ht["cat"] = cat;
                       }
                   }
                   ht["text"] = a.InnerText;
               }
               else
               {
                   ht["text"] = node.InnerText;
               }
           }
           return result;
       }


    }
}
